'use client'

import { useState, useEffect, useCallback, useRef } from 'react'
import * as Y from 'yjs'
import { WebsocketProvider } from 'y-websocket'
import { IndexeddbPersistence } from 'y-indexeddb'
import { CollaborativeUser, Cell, CellStyle } from '@/types/sheet'

interface UseYjsCollaborationProps {
  sheetId: string
  userId: string
  userName: string
}

interface UseYjsCollaborationReturn {
  ydoc: Y.Doc | null
  provider: WebsocketProvider | null
  collaborativeUsers: CollaborativeUser[]
  isConnected: boolean
  cells: Cell[]
  updateCell: (row: number, column: number, value: string, formula?: string) => void
  updateCellStyle: (row: number, column: number, style: CellStyle) => void
  updateCursor: (row: number, column: number) => void
  updateSelection: (startRow: number, startColumn: number, endRow: number, endColumn: number) => void
  loadInitialData: (cells: Cell[]) => void
}

export function useYjsCollaboration({
  sheetId,
  userId,
  userName
}: UseYjsCollaborationProps): UseYjsCollaborationReturn {
  const [ydoc, setYdoc] = useState<Y.Doc | null>(null)
  const [provider, setProvider] = useState<WebsocketProvider | null>(null)
  const [collaborativeUsers, setCollaborativeUsers] = useState<CollaborativeUser[]>([])
  const [isConnected, setIsConnected] = useState(false)
  const [cells, setCells] = useState<Cell[]>([])
  
  const ydocRef = useRef<Y.Doc | null>(null)
  const providerRef = useRef<WebsocketProvider | null>(null)
  const awarenessRef = useRef<any>(null)

  // 初始化 Yjs 文档和 WebSocket 提供者
  useEffect(() => {
    if (!sheetId) {
      console.warn('sheetId 为空，跳过协同初始化')
      return
    }

    // 使用默认用户信息如果为空
    const effectiveUserId = userId || 'anonymous'
    const effectiveUserName = userName || '匿名用户'

    console.log('=== 初始化协同连接 ===')
    console.log('sheetId:', sheetId)
    console.log('userId:', effectiveUserId)
    console.log('userName:', effectiveUserName)

    // 创建 Yjs 文档
    const doc = new Y.Doc()
    ydocRef.current = doc
    setYdoc(doc)

    // 获取 WebSocket URL
    const wsUrl = process.env.NEXT_PUBLIC_WS_URL || 'ws://localhost:1234'
    console.log('WebSocket URL:', wsUrl)

    // 创建 WebSocket 提供者
    const wsProvider = new WebsocketProvider(
      wsUrl,
      `sheet-${sheetId}`,
      doc,
      {
        connect: true
      }
    )

    providerRef.current = wsProvider
    setProvider(wsProvider)

    // 创建 IndexedDB 持久化
    const indexeddbProvider = new IndexeddbPersistence(`sheet-${sheetId}`, doc)

    // 获取 awareness 对象
    awarenessRef.current = wsProvider.awareness

    // 设置用户信息
    if (awarenessRef.current) {
      awarenessRef.current.setLocalStateField('user', {
        name: effectiveUserName,
        color: `#${Math.floor(Math.random()*16777215).toString(16)}`
      })
      console.log('设置用户信息:', effectiveUserName)
    }

    // 监听连接状态
    wsProvider.on('status', (event: any) => {
      console.log('WebSocket 状态变化:', event.status)
      setIsConnected(event.status === 'connected')
      
      if (event.status === 'connected') {
        console.log('✅ WebSocket 连接成功')
      } else if (event.status === 'disconnected') {
        console.log('❌ WebSocket 连接断开')
      }
    })

    // 监听连接错误
    wsProvider.on('connection-error', (error: any) => {
      console.error('WebSocket 连接错误:', error)
    })

    // 监听重连
    wsProvider.on('connection-close', () => {
      console.log('WebSocket 连接关闭，尝试重连...')
    })

    // 监听用户状态变化
    const handleAwarenessChange = () => {
      const users: CollaborativeUser[] = []
      awarenessRef.current.getStates().forEach((state: any, clientId: number) => {
        if (state.user) {
          users.push({
            id: clientId.toString(),
            name: state.user.name || 'Unknown',
            color: state.user.color || '#3B82F6',
            cursor: state.cursor || null,
            selection: state.selection || null
          })
        }
      })
      setCollaborativeUsers(users)
    }

    // 使用正确的事件监听方式
    if (awarenessRef.current) {
      awarenessRef.current.on('change', handleAwarenessChange)
    }

    // 设置单元格数据的 Yjs Map
    const cellsMap = doc.getMap('cells')
    const cursorsMap = doc.getMap('cursors')
    const selectionsMap = doc.getMap('selections')

    // 监听单元格数据变化
    const updateCells = () => {
      const cellsArray: Cell[] = []
      cellsMap.forEach((cellData: any, key: string) => {
        const [row, column] = key.split('-').map(Number)
        cellsArray.push({
          id: cellData.id || `${row}-${column}`,
          row,
          column,
          value: cellData.value || '',
          formula: cellData.formula || '',
          style: cellData.style || {},
          sheetId,
          createdAt: cellData.createdAt ? new Date(cellData.createdAt) : new Date(),
          updatedAt: cellData.updatedAt ? new Date(cellData.updatedAt) : new Date()
        })
      })
      setCells(cellsArray)
    }

    // 注意：初始数据加载由页面组件的 fetchSheet() 处理
    // 这里不需要重复请求，避免重复 API 调用

    // 初始更新
    updateCells()

    // 监听变化
    cellsMap.observe(updateCells)

    // 清理函数
    return () => {
      cellsMap.unobserve(updateCells)
      
      // 移除 awareness 事件监听器
      if (awarenessRef.current) {
        awarenessRef.current.off('change', handleAwarenessChange)
      }
      
      wsProvider.destroy()
      indexeddbProvider.destroy()
      doc.destroy()
    }
  }, [])

  // 更新单元格
  const updateCell = useCallback((row: number, column: number, value: string, formula?: string) => {
    if (!ydocRef.current) return

    const cellsMap = ydocRef.current.getMap('cells')
    const key = `${row}-${column}`
    const existingCell = cellsMap.get(key) as Cell | undefined
    
    cellsMap.set(key, {
      id: existingCell?.id || `${row}-${column}`,
      row,
      column,
      value,
      formula: formula || existingCell?.formula || '',
      style: existingCell?.style || {},
      sheetId,
      createdAt: existingCell?.createdAt || new Date().toISOString(),
      updatedAt: new Date().toISOString()
    })
  }, [sheetId])

  // 更新单元格样式
  const updateCellStyle = useCallback((row: number, column: number, style: CellStyle) => {
    if (!ydocRef.current) return

    const cellsMap = ydocRef.current.getMap('cells')
    const key = `${row}-${column}`
    const existingCell = cellsMap.get(key) as Cell | undefined
    
    cellsMap.set(key, {
      id: existingCell?.id || `${row}-${column}`,
      row,
      column,
      value: existingCell?.value || '',
      formula: existingCell?.formula || '',
      style,
      sheetId,
      createdAt: existingCell?.createdAt || new Date().toISOString(),
      updatedAt: new Date().toISOString()
    })
  }, [sheetId])

  // 加载初始数据
  const loadInitialData = useCallback((cells: Cell[]) => {
    if (!ydocRef.current || !cells || cells.length === 0) return
    
    const cellsMap = ydocRef.current.getMap('cells')
    
    // 清空现有数据
    cellsMap.clear()
    
    // 加载新数据
    cells.forEach(cell => {
      const key = `${cell.row}-${cell.column}`
      cellsMap.set(key, {
        id: cell.id || `${cell.row}-${cell.column}`,
        row: cell.row,
        column: cell.column,
        value: cell.value || '',
        formula: cell.formula || '',
        style: cell.style || {},
        sheetId,
        createdAt: cell.createdAt ? 
          (typeof cell.createdAt === 'string' ? cell.createdAt : cell.createdAt.toISOString()) : 
          new Date().toISOString(),
        updatedAt: cell.updatedAt ? 
          (typeof cell.updatedAt === 'string' ? cell.updatedAt : cell.updatedAt.toISOString()) : 
          new Date().toISOString()
      })
    })
    
    console.log('Loaded initial data:', cells.length, 'cells')
  }, [sheetId])

  // 更新光标位置
  const updateCursor = useCallback((row: number, column: number) => {
    if (!awarenessRef.current) return

    awarenessRef.current.setLocalStateField('cursor', { row, column })
  }, [])

  // 更新选择区域
  const updateSelection = useCallback((startRow: number, startColumn: number, endRow: number, endColumn: number) => {
    if (!awarenessRef.current) return

    awarenessRef.current.setLocalStateField('selection', {
      startRow,
      startColumn,
      endRow,
      endColumn
    })
  }, [])

  return {
    ydoc,
    provider,
    collaborativeUsers,
    isConnected,
    cells,
    updateCell,
    updateCellStyle,
    updateCursor,
    updateSelection,
    loadInitialData
  }
}
